package socket;

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

/**
 * 聊天室客户端
 */
public class Client1 {
    /*
        java.net.Socket : 套接字
        Socket封装了TCP协议的连接和通讯细节，使得我们使用他们可以很方便的与远端计算机建立连接并
        基于两个流(一个输入一个输出)的读写完成与远端计算机的数据交换从而实现对应的网络应用.
     */
    private Socket socket;

    /**
     * 构造方法，用于初始化客户端
     */
    public Client1() {
        try {
            /*
                实例化Socket时需要传入两个参数:
                参数1：服务端的IP地址，如果连接本机则可以使用localhost

                参数2：服务端程序在服务端计算机上申请的服务端口。
                我们通过服务端的IP找到网络上服务端所在的计算机，通过端口找到该计算机上运行的服务端
                应用程序。

                实例化Socket的过程就是按照给定的地址与服务端建立连接的过程，如果连接失败则会抛出
                异常。
             */
            System.out.println("连接服务端。。。");
            socket = new Socket("localhost", 8088);//192.168.27.44//ipconfig
            System.out.println("与服务的建立连接...");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 客户端开始工作的方法
     */
    public void start() {

        try {
            //先启动用于服务服务端发送过来消息的线程
            ServerHandLer ler = new ServerHandLer();
            Thread t = new Thread(ler);
            t.start();
            /*
                Socket提供的方法:
                OutputStream getOutputStream()
                获取一个字节输出流，通过这个流写出的字节会发送给远端计算机.

                注释:该方法无论调用多少次，返回的输出流始终是同一个.
             */
            OutputStream out = socket.getOutputStream();
            OutputStreamWriter osr = new OutputStreamWriter(out, "UTF-8");
            BufferedWriter bwr = new BufferedWriter(osr);
            PrintWriter pwr = new PrintWriter(bwr, true);

            Scanner scan = new Scanner(System.in);
            String len ;
            while (true) {
                len = scan.nextLine();
                if("exit".equalsIgnoreCase(len)){
                    break;
                }
                pwr.println("客户端1说:"+len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                //close操作中会给远端计算机发送断开信号。同时关闭对应的输入流与输出流.
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        Client1 client = new Client1();
        client.start();
    }
    private class ServerHandLer implements Runnable{
        public void run(){
            try {
                InputStream is = socket.getInputStream();
                InputStreamReader isr = new InputStreamReader(is,"UTF-8");
                BufferedReader br = new BufferedReader(isr);
                String bo;
                while ((bo=br.readLine())!=null){
                    System.out.println(bo);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
